package cn.ztuo.bitrade.service;

import cn.ztuo.bitrade.constant.PageModel;
import cn.ztuo.bitrade.constant.TransactionType;
import cn.ztuo.bitrade.dao.ContractWalletMapper;
import cn.ztuo.bitrade.dao.OtcWalletDao;
import cn.ztuo.bitrade.dto.ContractWalletDTO;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.util.MessageResult;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class ContractWalletService {

    @Autowired
    private ContractWalletMapper contractWalletMapper;
    @Autowired
    private OtcWalletDao otcWalletDao;
    //JPA查询工厂
    @Autowired
    protected JPAQueryFactory queryFactory;
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    private MemberTransactionService transactionService;

    public List<ContractWallet> findAllByMemberId(Long id) {
        return contractWalletMapper.findAllByMemberId(id);
    }


    public ContractWallet save(ContractWallet contractWa) {
        return contractWalletMapper.save(contractWa);
    }

    public ContractWallet findByCoinIdAndMemberId(String name, Long id) {
        return contractWalletMapper.findByMemberId(id);
    }

    /**
     * 币币转合约
     *
     * @param memberWallet
     * @param contractWallet
     * @param amount
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int cointoCon(MemberWallet memberWallet, ContractWallet contractWallet, BigDecimal amount) {
        //扣减币币账户
        memberWalletService.decreaseBalance(memberWallet.getId(), amount);
        //添加合约账户
        int addResult = contractWalletMapper.addwallet(contractWallet.getId(), amount);
        if (addResult == 0) {
            return 0;
        }
        //增加划转记录
        MemberTransaction transaction = new MemberTransaction();
        transaction.setAmount(amount);
        transaction.setSymbol(memberWallet.getCoin().getName());
        transaction.setAddress("");
        transaction.setMemberId(memberWallet.getMemberId());
        transaction.setType(TransactionType.COIN_TWO_CONTRACT);
        transaction.setFee(BigDecimal.ZERO);
        transaction.setCreateTime(new Date());
        transactionService.save(transaction);
        return 1;
    }
    /**
     * 合约转币币
     *
     *
     *
     * @param contractWallet
     * @param amount
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int conToCoin(MemberWallet memberWallet, ContractWallet contractWallet, BigDecimal amount) {
        //扣减合约账户
        int i= contractWalletMapper.decreaseBalance(contractWallet.getId(),amount);
        if (i == 0){
            return 0;
        }
        //增加币币账户
         memberWalletService.increaseBalance(memberWallet.getId(),amount);
        //增加划转记录
        MemberTransaction transaction = new MemberTransaction();
        transaction.setAmount(amount);
        transaction.setSymbol(memberWallet.getCoin().getName());
        transaction.setAddress("");
        transaction.setMemberId(memberWallet.getMemberId());
        transaction.setType(TransactionType.CONTRACT_TWO_COIN);
        transaction.setFee(BigDecimal.ZERO);
        transaction.setCreateTime(new Date());
        transactionService.save(transaction);
        return 1;
    }
    @Transactional(rollbackFor = Exception.class)
    public void findByBalancedongjie(Long memberId, BigDecimal sub,BigDecimal proxide) {
        contractWalletMapper.findByBalancedongjie(memberId,sub,proxide);
    }

    public ContractWallet findByMemberId(Long memberId) {
        return contractWalletMapper.findByMemberId(memberId);
    }
    @Transactional(rollbackFor = Exception.class)
    public MessageResult thawBalance(ContractWallet contractWallet, BigDecimal amount) {
        int ret = contractWalletMapper.thawBalance(contractWallet.getId(), amount);
        if (ret > 0) {
            return MessageResult.success();
        } else {
            return MessageResult.error("Information Expired");
        }
    }
    @Transactional(rollbackFor = Exception.class)
    public MessageResult addfrozenBalance(ContractWallet exCoinWallet, BigDecimal sub) {
        Long id = exCoinWallet.getId();
        int ret = contractWalletMapper.addfrozenBalance(id,sub);
        if (ret > 0) {
            return MessageResult.success();
        } else {
            return MessageResult.error("Information Expired");
        }

    }

    /**
     * 合约资产展示
     * @param predicates
     * @param qMember
     * @param qContractWallet
     * @param pageModel
     * @return
     */
    public Page<ContractWalletDTO> joinFind(List<Predicate> predicates, QMember qMember, QContractWallet qContractWallet, PageModel pageModel){
        List<OrderSpecifier> orderSpecifiers = pageModel.getOrderSpecifiers();
        predicates.add(qMember.id.eq(qContractWallet.memberId));
        JPAQuery<ContractWalletDTO> query = queryFactory.select(
                Projections.fields(
                        ContractWalletDTO.class,
                        qContractWallet.id.as("id"),
                        qContractWallet.memberId.as("memberId"),
                        qMember.username,
                        qMember.realName.as("realName"),
                        qMember.email,qMember.mobilePhone.as("mobilePhone"),
                        qContractWallet.balance,qContractWallet.coinId,
                        qContractWallet.frozenBalance.as("frozenBalance"),
                        qContractWallet.balance.add(qContractWallet.frozenBalance).as("allBalance"))).from(QMember.member,QContractWallet.contractWallet).where
                (predicates.toArray(new Predicate[predicates.size()])).orderBy(orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]));
        List<ContractWalletDTO> content = query.offset((pageModel.getPageNo()-1)*pageModel.getPageSize()).limit(pageModel.getPageSize()).fetch();
        long total =  query.fetchCount();
        return new PageImpl<>(content,pageModel.getPageable(),total);
    }


    public void decreaseFrozen(Long walletId,BigDecimal amount){
        contractWalletMapper.decreaseFrozen(walletId,amount);
    }

    @Transactional(rollbackFor = Exception.class)
    public int updateCost(Long memberId,BigDecimal cost,ContractOrderPositionType positionType) {
        ContractWallet coinWallet = contractWalletMapper.findByMemberId(memberId);
        //RISE:开多 FALL:开空
        if (positionType == ContractOrderPositionType.RISE) {
            //资金费率为正 开多减 开空加
            BigDecimal cost1 = coinWallet.getBalance().subtract(cost);
            if(cost1.compareTo(BigDecimal.ZERO)<0) cost1= BigDecimal.ZERO;
            coinWallet.setBalance(cost1);
        } else {
            //资金费率为负 开多加 开空减
            BigDecimal cost2 = coinWallet.getBalance().add(cost);
            if(cost2.compareTo(BigDecimal.ZERO)<0) cost2= BigDecimal.ZERO;
            coinWallet.setBalance(cost2);
        }
       ContractWallet contract = contractWalletMapper.save(coinWallet);
        if(contract==null){
           return 0;
       }else{
           return 1;
       }
    }
}
